/**
 * @author: yyq
 * @date: 2025年3月14日 13:46:48
 * @description: 
 */
package com.sheepone.monitor.runner;

import com.sheepone.monitor.codec.SheeponePackage;
import com.sheepone.monitor.config.MonitorConfig;
import com.sheepone.monitor.core.AbstractSheeponeChannelInitializer;
import com.sheepone.monitor.enums.MonitorRunnerStatusEnum;
import com.sheepone.monitor.runner.listener.MonitorRunnerListenerAdapter;
import com.sheepone.webdev.log.WebDevLogger;

import io.netty.channel.Channel;

/**
 * @author: yyq
 * @date: 2025年3月14日 13:46:48
 * @description:
 */
public abstract class AbstractMonitorRunnerHolder<C extends MonitorConfig, I extends AbstractSheeponeChannelInitializer> {
    protected AbstractMonitorRunner<C, I> runner;
    protected C config;
    private MonitorRunnerStatusEnum status = MonitorRunnerStatusEnum.DEACTIVATE;
    private Channel channel;

    private static WebDevLogger logger = WebDevLogger.getLogger(AbstractMonitorRunnerHolder.class);

    public AbstractMonitorRunnerHolder(C config) {
        this.config = config;
    }

    protected abstract AbstractMonitorRunner<C, I> runner();

    protected abstract I channelInitializer();

    protected abstract void afterInitd();

    private void init() {
        this.runner = runner();
        this.runner.addListener(new MonitorRunnerListenerAdapter() {
            @Override
            public void startSuccessfully(Channel channel) {
                AbstractMonitorRunnerHolder.this.channel = channel;
                AbstractMonitorRunnerHolder.this.status = MonitorRunnerStatusEnum.RUNNING;
            }

            @Override
            public void stopSuccessfully(Channel channel) {
                AbstractMonitorRunnerHolder.this.channel = null;
                AbstractMonitorRunnerHolder.this.status = MonitorRunnerStatusEnum.SHUTDOWN;
            }
        });
    }

    public void run() {
        if (status != MonitorRunnerStatusEnum.DEACTIVATE) {
            // TODO logger
            return;
        }
        this.status = MonitorRunnerStatusEnum.INIT;
        // 1、初始化runner（由子类实例化具体的runner）
        // 2、给runner添加必须的listeners（监听runner的启停状态处理，例如拿到可以进行网络通信的Channel）
        init();
        // 3、init后处理（提供给子类的扩展点）
        afterInitd();
        this.status = MonitorRunnerStatusEnum.STARTING;
        // 4、异步启动runner
        new Thread() {
            @Override
            public void run() {
                runner.run(channelInitializer());
            }
        }.start();
    }

    protected void writeAndFlush(SheeponePackage msg) {
        if (channel == null || status != MonitorRunnerStatusEnum.RUNNING) {
            // TODO logger or exception
            return;
        }
        channel.writeAndFlush(msg);
    }

    public boolean isDeactivate() {
        return status == MonitorRunnerStatusEnum.DEACTIVATE;
    }

    public boolean isInit() {
        return status == MonitorRunnerStatusEnum.INIT;
    }

    public boolean isStarting() {
        return status == MonitorRunnerStatusEnum.STARTING;
    }

    public boolean isRunning() {
        return status == MonitorRunnerStatusEnum.RUNNING;
    }

    public boolean isStopping() {
        return status == MonitorRunnerStatusEnum.STOPPING;
    }

    public boolean isShutdown() {
        return status == MonitorRunnerStatusEnum.SHUTDOWN;
    }
}
